package com.enjoyor.soa.traffic.server.tsms.thead;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import com.alibaba.fastjson.JSONObject;
import com.enjoyor.soa.traffic.api.dto.tsms.RouteInfoDto;
import com.enjoyor.soa.traffic.core.tsms.domain.RltRouteDevice;
import com.enjoyor.soa.traffic.core.tsms.domain.RouteInfo;
import com.enjoyor.soa.traffic.core.tsms.domain.SchemeInfo;
import com.enjoyor.soa.traffic.core.tsms.service.IRouteInfoService;
import com.enjoyor.soa.traffic.core.tsms.service.ISchemeInfoService;
import com.enjoyor.soa.traffic.server.tsms.common.RehearseGlobal;
import com.enjoyor.soa.traffic.server.tsms.dubbo.impl.DubboServerPushServiceImpl;
import com.enjoyor.soa.traffic.server.tsms.helper.EntityChangeHelper;
import com.enjoyor.soa.traffic.server.tsms.helper.RouteClashHelper;
import com.enjoyor.soa.traffic.server.tsms.helper.RouteHandleHelper;
import com.enjoyor.soa.traffic.util.helper.GeoToolsHelper;
import com.enjoyor.soa.traffic.util.helper.GeomtryHelper;
import com.enjoyor.soa.traffic.util.helper.TimeHelper;

import oracle.spatial.geometry.JGeometry;

/**
 * 预演的推送控制
 * 
 */
public class RehearseThead extends Thread {
	private int timeNum = 30;//冲突校验的时间间隔数
	private int clashDistance = 200;//车队冲突距离

	private volatile int status = 1; // 状态值
	private final int STOP = -1;// 停止
	private final int SUSPEND = 0;// 暂停
	private final int RUNNING = 1; // 运行
	private String browserId; // 浏览器id
	volatile double times = 1; // 倍率
	String executeDate; //执行日期
	double rout;//执行进度百分比
	double routFlag;//执行进度百分比（调用线程的初始进度，防止进度条错乱）
	boolean isOnlyRoute = false;//是否只修改进度
	long realTime;//当前执行时间戳
	private List<Map<String, Object>> taskRouteList;
	private int routeSplitTime;
	private long minBeginLong;
	private long maxEndLong;
	Map<String, Map<String, Map>> taskByTimeMap;
	Map<String, Map<String, Object>> clashMap;
	//List<RehearseThead> threadlist;// 存储线程名list
	DubboServerPushServiceImpl dubboServerPushServiceImpl; // 推送
	IRouteInfoService iRouteInfoService;
	ISchemeInfoService iSchemeInfoService; //方案实现接口
	GeoToolsHelper geoToolsHelper = new GeoToolsHelper(); // geo计算方法

	/**
	 * 预演进度条的时间推送控制
	 * 
	 * @param taskRouteList 所有线路信息集合
	 * 		@param taskId 任务ID
	 * 		@param taskName 任务名称
	 * 		@param routeInfo 线路信息
	 * 		@param beginTime 执行开始时间
	 * 		@param endTime 执行结束时间
	 * 		@param startLength 距线路起点距离
	 * @param routeSplitTime             线路拆分时间间隔(ms)
	 * @param minBeginLong               任务最小开始时间
	 * @param maxEndLong                 任务最大结束时间
	 * @param rout                       执行百分比
	 * @param times                      倍率
	 * @param browserId                  浏览器id
	 * @param threadlist                 存储线程名list
	 * @param dubboServerPushServiceImpl 推送方法
	 */
	@SuppressWarnings("unchecked")
	public RehearseThead(String executeDate, double rout, double times, String browserId, int routeSplitTime, 
			DubboServerPushServiceImpl dubboServerPushServiceImpl, 
			ISchemeInfoService iSchemeInfoService, IRouteInfoService iRouteInfoService, List<RouteInfoDto> routeInfoDtoList) {
		this.executeDate = executeDate;
		this.routeSplitTime = routeSplitTime;
		this.times = times;
		this.rout = rout;
		this.routFlag = rout;
		this.browserId = browserId;
		//this.threadlist = threadlist;
		this.dubboServerPushServiceImpl = dubboServerPushServiceImpl;
		this.iRouteInfoService = iRouteInfoService;
		this.iSchemeInfoService = iSchemeInfoService;
		if(routeInfoDtoList != null && routeInfoDtoList.size() > 0) {
			this.changeRoute(routeInfoDtoList);
		}else {
			String poolKey = browserId+"_"+executeDate;
			Map<String, Object> rehearseMap = RehearseGlobal.RehearseDataPool.get(poolKey);
			//缓存中有冲突数据 就直接使用，没有就重新查询当天方案进行冲突校验
			if(rehearseMap != null && !rehearseMap.isEmpty()) {
				this.minBeginLong = (long)rehearseMap.get("minBeginLong");
				this.maxEndLong = (long)rehearseMap.get("maxEndLong");
				this.taskRouteList = (List<Map<String, Object>>)rehearseMap.get("taskRouteList");
				this.taskByTimeMap = (Map<String, Map<String, Map>>)rehearseMap.get("taskByTimeMap");
				this.clashMap = (Map<String, Map<String, Object>>)rehearseMap.get("clashMap");
			}else {
				rehearseMap = new HashMap<String, Object>();
				List<Map<String, Object>> schemeObjList = (List<Map<String, Object>>) iSchemeInfoService
						.getPreviewSchemeList(executeDate, executeDate, false);
				if (schemeObjList.size() > 0) {
					List<SchemeInfo> schemeList = (List<SchemeInfo>) schemeObjList.get(0).get("schemeList"); // 当天多个方案
					Map<String, Object> taskRouteMap = new HashMap<String, Object>();
					if(schemeList != null && schemeList.size() > 0) {
						//根据方案获取线路列表信息
						taskRouteMap = RouteHandleHelper.getRouteListByScheme(schemeList, iRouteInfoService);
						if(taskRouteMap != null && !taskRouteMap.isEmpty()) {
							this.minBeginLong = (long)taskRouteMap.get("minBeginLong");
							this.maxEndLong = (long)taskRouteMap.get("maxEndLong");
							this.taskRouteList = (List<Map<String, Object>>)taskRouteMap.get("taskRouteList");
						}else {
							return;
						}
						//执行线路按规定时间间隔进行拆分
						if(this.taskRouteList != null && this.taskRouteList.size() > 0) {
							//this.taskByTimeMap = RouteHandleHelper.routeInfoByTime(this.taskRouteList, routeSplitTime, false);
							this.taskByTimeMap = new HashMap<String, Map<String,Map>>();
							Vector<Thread> ts = new Vector<Thread>();
							for (Map<String, Object> taskRouteMapTemp : taskRouteList) {
								Thread t = new Thread(new Runnable() {
									@Override
									public void run() {
										RouteHandleHelper.routeInfoByTimeOne(taskByTimeMap, taskRouteMapTemp, routeSplitTime, false);
									}
								});
								ts.add(t);
								t.start();
							}
							for (Thread t : ts) {
								try {
									t.join();//等待所有线路拆分完成
								} catch (InterruptedException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							}
							
							if(this.taskByTimeMap != null && !this.taskByTimeMap.isEmpty()) {
								//根据线路分隔数据分析冲突情况
								this.clashMap =  RouteClashHelper.routeClashAnalysis(taskByTimeMap, taskRouteList, minBeginLong, maxEndLong, 
										routeSplitTime, timeNum, clashDistance, true);
							}
							
							rehearseMap.putAll(taskRouteMap);//线路信息
							rehearseMap.put("taskByTimeMap", this.taskByTimeMap);//线路拆分信息
							rehearseMap.put("clashMap", this.clashMap);//线路冲突信息
							RehearseGlobal.RehearseDataPool.put(poolKey, rehearseMap);
						}
					}
				}
			}
		}
		double timeRout = (this.maxEndLong - this.minBeginLong) * rout;
		this.realTime = minBeginLong + (long)Math.floor(timeRout/this.routeSplitTime)*this.routeSplitTime;

		//推送开始预演消息
		com.alibaba.fastjson.JSONObject jsonObject2 = new com.alibaba.fastjson.JSONObject();
		jsonObject2.put("type", "begin");
		jsonObject2.put("recordTime", TimeHelper.dateToLongString());
		jsonObject2.put("content", "预演开始!");
		dubboServerPushServiceImpl.pushMessage("" + browserId, jsonObject2);
	}
	
	//如果修改线路，则需要重新计算冲突以及更新缓存数据,
	@SuppressWarnings("unchecked")
	public void changeRoute(List<RouteInfoDto> routeInfoDtoList) {
		//把修改的线路信息List转换为Map,便于使用
		Map<String, RouteInfo> routeInfoMap = new HashMap<String, RouteInfo>();
		for(RouteInfoDto routeInfoDto : routeInfoDtoList) {
			RouteInfo routeInfo = EntityChangeHelper.routeInfoDtoToPojo(routeInfoDto);
			String strArea = routeInfo.getStrArea();
			JGeometry jGeometry = GeomtryHelper.getGeomWithGson(strArea);
			routeInfo.setRouteGeo(jGeometry);
			routeInfoMap.put(routeInfo.getRouteId(), routeInfo);
		}
		//查询当天方案、线路数据
		List<Map<String, Object>> schemeObjList = (List<Map<String, Object>>) iSchemeInfoService
				.getPreviewSchemeList(executeDate, executeDate, false);
		if (schemeObjList.size() > 0) {
			List<SchemeInfo> schemeList = (List<SchemeInfo>) schemeObjList.get(0).get("schemeList"); // 当天多个方案
			Map<String, Object> taskRouteMap = new HashMap<String, Object>();
			if(schemeList != null && schemeList.size() > 0) {
				//根据方案获取线路列表信息
				taskRouteMap = RouteHandleHelper.getRouteListBySchemeNew(schemeList, routeInfoMap, iRouteInfoService);
				if(taskRouteMap != null && !taskRouteMap.isEmpty()) {
					this.minBeginLong = (long)taskRouteMap.get("minBeginLong");
					this.maxEndLong = (long)taskRouteMap.get("maxEndLong");
					this.taskRouteList = (List<Map<String, Object>>)taskRouteMap.get("taskRouteList");
				}else {
					return;
				}
				//执行线路按规定时间间隔进行拆分
				if(this.taskRouteList != null && this.taskRouteList.size() > 0) {
					//this.taskByTimeMap = RouteHandleHelper.routeInfoByTime(this.taskRouteList, routeSplitTime, false);
					this.taskByTimeMap = new HashMap<String, Map<String,Map>>();
					Vector<Thread> ts = new Vector<Thread>();
					for (Map<String, Object> taskRouteMapTemp : taskRouteList) {
						Thread t = new Thread(new Runnable() {
							@Override
							public void run() {
								RouteHandleHelper.routeInfoByTimeOne(taskByTimeMap, taskRouteMapTemp, routeSplitTime, false);
							}
						});
						ts.add(t);
						t.start();
					}
					for (Thread t : ts) {
						try {
							t.join();//等待所有线路拆分完成
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					if(this.taskByTimeMap != null && !this.taskByTimeMap.isEmpty()) {
						//根据线路分隔数据分析冲突情况
						this.clashMap =  RouteClashHelper.routeClashAnalysis(this.taskByTimeMap, taskRouteList, 
								this.minBeginLong, this.maxEndLong, routeSplitTime, timeNum, clashDistance, true);
					}
					//更新缓存数据
					String poolKey = browserId+"_"+executeDate;
					Map<String, Object> rehearseMap = new HashMap<String, Object>();
					rehearseMap.putAll(taskRouteMap);//线路信息
					rehearseMap.put("taskByTimeMap", this.taskByTimeMap);//线路拆分信息
					rehearseMap.put("clashMap", this.clashMap);//线路冲突信息
					RehearseGlobal.RehearseDataPool.put(poolKey, rehearseMap);
				}
				List<Map<String, Object>> clashInfoList = new ArrayList<Map<String, Object>>();
				boolean isClash = false;
				if(this.clashMap != null && !this.clashMap.isEmpty()) {
					isClash = true;
					for (Map.Entry<String, Map<String, Object>> m : this.clashMap.entrySet()) {
						Map<String, Object> clashInfoMap = RouteClashHelper.getClashInfoByChange(m.getValue());
						clashInfoMap.put("clashId", m.getKey());
						clashInfoList.add(clashInfoMap);
					}
					//clashInfoList排序(根据冲突ID后面的时间戳);
					Collections.sort(clashInfoList, new Comparator<Map<String, Object>>() {
						/*
						 * int compare(Person p1, Person p2) 返回一个基本类型的整型， 返回负数表示：p1
						 * 小于p2， 返回0 表示：p1和p2相等， 返回正数表示：p1大于p2
						 */
						@Override
						public int compare(Map<String, Object> p1, Map<String, Object> p2) {
							String clashId1= ((String)p1.get("clashId")).split("_")[1];
							String clashId2= ((String)p2.get("clashId")).split("_")[1];
							if (Long.parseLong(clashId1) > Long.parseLong(clashId2)) {
								return 1;
							}
							if (Long.parseLong(clashId1) == Long.parseLong(clashId2)) {
								return 0;
							}
							return -1;
						}

					});
				}
				com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
				jsonObject.put("executeDate", executeDate);
				jsonObject.put("isClash", isClash);
				jsonObject.put("clashContent", clashInfoList);
				dubboServerPushServiceImpl.pushMessage("" + browserId, jsonObject); // 推送冲突信息
			}
		}
	}
	
	public void setTimes(double times) {
		this.times = times;
	}
	public double getTimes() {
		return times;
	}
	public double getRout() {
		return rout;
	}
	/**
	 * 恢复
	 */
	public void setResume() {
		status = RUNNING;
	}
	/**
	 * 挂起
	 */
	public void setSuspend() {
		status = SUSPEND;
	}
	/**
	 * 停止
	 */
	public void setStop() {
		status = STOP;
	}
	public int getStatus() { // 获取状态
		return status;
	}
	public void setStatus(int status) { // 设置状态
		this.status = status;
	}
	// 设置执行进度百分比
	public void setRout(double rout) {
		this.routFlag = rout;
		this.rout = rout;	
		double timeRout = (this.maxEndLong - this.minBeginLong) * rout;
		this.realTime = minBeginLong + (long)Math.floor(timeRout/this.routeSplitTime)*this.routeSplitTime;
		this.isOnlyRoute = true;
	}
	//获取预演执行时间
	public String getExecuteDate() {
		return executeDate;
	}
	
	
	@SuppressWarnings("unchecked")
	public synchronized void run() {

		while (realTime >= minBeginLong && realTime <= maxEndLong && (getStatus() != STOP)) {
			// 判断是否挂起
			if (getStatus() == SUSPEND) {
				// 若线程挂起则阻塞自己
				// this.wait();
				// System.out.println("线程暂停...");
			} else {
				Map<String, Map> realTimeMap = taskByTimeMap.get(String.valueOf(realTime));
				if(realTimeMap != null && !realTimeMap.isEmpty()) {
					for(int a = 0; a < taskRouteList.size(); a++){
						Map<String, Object> taskRouteMap = taskRouteList.get(a);
					    String taskId = (String)taskRouteMap.get("taskId");//任务ID
					    //String taskName = (String)taskRouteMap.get("taskName");//任务名称
					    RouteInfo routeInfo = (RouteInfo)taskRouteMap.get("routeInfo");//线路信息
						//String beginTime = (String)taskRouteMap.get("beginTime");//开始执行时间
						//String endTime = (String)taskRouteMap.get("endTime");//结束执行时间
					    //double startLength = (double)taskRouteMap.get("startLength");//距线路起点距离

						String routeId = routeInfo.getRouteId();//线路编号
						int routeLength = routeInfo.getRouteLength().intValue();//线路总长度

						Map<String, Object> objectMap = realTimeMap.get(taskId);
						if(objectMap != null && !objectMap.isEmpty()) {
							int iPoint = (int)objectMap.get("iPoint");
							double pointX = (double)objectMap.get("x");
							double pointY = (double)objectMap.get("y");
							double distanceStartLength = (double)objectMap.get("distanceStartLength");//距起点距离
							int distanceNextLength = (int)objectMap.get("distanceNextLength");//距下个途径点距离
							double speed = (double)objectMap.get("speed");
							boolean videoFlag = (boolean)objectMap.get("videoFlag");
							Map<String, RltRouteDevice> videoMap = (Map<String, RltRouteDevice>)objectMap.get("videoMap");
							boolean signalFlag = (boolean)objectMap.get("signalFlag");
							Map<String, RltRouteDevice> signalMap = (Map<String, RltRouteDevice>)objectMap.get("signalMap");
							double percent = distanceStartLength/routeLength;
							//推送视频点位
							if(videoFlag || isOnlyRoute) {
								JSONObject jsonObject = new JSONObject();
								Map<String, Object> deviceMap = new HashMap<String, Object>();
								List<RltRouteDevice> videoList = new ArrayList<RltRouteDevice>();
								for (Map.Entry<String, RltRouteDevice> m : videoMap.entrySet()) {
									videoList.add(m.getValue());
								}
								//按距离排序
								videoList = RouteHandleHelper.rltRouteDeviceSort(videoList);
								deviceMap.put("cameradevice", videoList);
								jsonObject.put(routeId, deviceMap);
								dubboServerPushServiceImpl.pushMessage("" + browserId, jsonObject);
							}
							//推送信号机
							if(signalFlag || isOnlyRoute) {
								JSONObject jsonObject = new JSONObject();
								Map<String, Object> deviceMap = new HashMap<String, Object>();
								List<RltRouteDevice> beforeSignalList = new ArrayList<RltRouteDevice>();
								List<RltRouteDevice> afterSignalList = new ArrayList<RltRouteDevice>();
								for (Map.Entry<String, RltRouteDevice> m : signalMap.entrySet()) {
									if(Integer.parseInt(m.getValue().getId()) < 1) {
										beforeSignalList.add(m.getValue());
									}else {
										afterSignalList.add(m.getValue());
									}
								}
								//按距离排序
								beforeSignalList = RouteHandleHelper.rltRouteDeviceSort(beforeSignalList);
								afterSignalList = RouteHandleHelper.rltRouteDeviceSort(afterSignalList);
								deviceMap.put("beforedevice", beforeSignalList);
								deviceMap.put("afterdevice", afterSignalList);
								jsonObject.put(routeId, deviceMap);
								dubboServerPushServiceImpl.pushMessage("" + browserId, jsonObject);
							}
							isOnlyRoute = false;//重置修改进度标识
							//推送实时坐标等信息
							com.alibaba.fastjson.JSONObject jsonObject2 = new com.alibaba.fastjson.JSONObject();
							Map<String, Object> routemap = new HashMap<String, Object>();
							routemap.put("x", pointX);
							routemap.put("y", pointY);
							routemap.put("percent", percent);//已行驶百分比
							routemap.put("speed", speed);//行驶速度
							routemap.put("distanceStartLength", distanceStartLength);//距起点距离
							routemap.put("distanceNextLength", distanceNextLength);//距下个途径点距离
							routemap.put("arrivedPointIdx", iPoint);//经过的途径点序号
							jsonObject2.put(routeId, routemap);
							dubboServerPushServiceImpl.pushMessage("" + browserId, jsonObject2);
						}
					}
				}
				//推送冲突数据
				if(clashMap != null && !clashMap.isEmpty()) {
					//线路冲突
					String routeKey = "route_"+String.valueOf(realTime);
					Map<String, Object> routeClashMap = clashMap.get(routeKey);
					if(routeClashMap != null && !routeClashMap.isEmpty()) {
						JSONObject jsonObject = new JSONObject();
						List<Map<String, Object>> clashInfoList = new ArrayList<Map<String, Object>>(); 
						Map<String, Object> clashInfoMap =  RouteClashHelper.getClashInfoByChange(routeClashMap);
						clashInfoMap.put("clashId", routeKey);
						clashInfoList.add(clashInfoMap);
						jsonObject.put("clashAlarm", clashInfoList);
						dubboServerPushServiceImpl.pushMessage("" + browserId, jsonObject);
					}
					//视频抢占
					String videoKey = "video_"+String.valueOf(realTime);
					Map<String, Object> videoClashMap = clashMap.get(videoKey);
					if(videoClashMap != null && !videoClashMap.isEmpty()) {
						JSONObject jsonObject = new JSONObject();
						List<Map<String, Object>> clashInfoList = new ArrayList<Map<String, Object>>(); 
						Map<String, Object> clashInfoMap =  RouteClashHelper.getClashInfoByChange(videoClashMap);
						clashInfoMap.put("clashId", videoKey);
						clashInfoList.add(clashInfoMap);
						jsonObject.put("clashAlarm", clashInfoList);
						dubboServerPushServiceImpl.pushMessage("" + browserId, jsonObject);
					}
					//信号机抢占
					String signalKey = "signal_"+String.valueOf(realTime);
					Map<String, Object> signalClashMap = clashMap.get(signalKey);
					if(signalClashMap != null && !signalClashMap.isEmpty()) {
						JSONObject jsonObject = new JSONObject();
						List<Map<String, Object>> clashInfoList = new ArrayList<Map<String, Object>>(); 
						Map<String, Object> clashInfoMap =  RouteClashHelper.getClashInfoByChange(signalClashMap);
						clashInfoMap.put("clashId", signalKey);
						clashInfoList.add(clashInfoMap);
						jsonObject.put("clashAlarm", clashInfoList);
						dubboServerPushServiceImpl.pushMessage("" + browserId, jsonObject);
					}
				}
				
				JSONObject routJsonObject = new JSONObject();
				rout = ((realTime-minBeginLong)*1.0d)/(maxEndLong-minBeginLong);
				routJsonObject.put("rout", rout);//实时进度百分比
				routJsonObject.put("realTime", TimeHelper.dateToLongString(new Date(realTime)));//实时执行时间
				routJsonObject.put("rout_flag", routFlag);//初始进度百分比
				dubboServerPushServiceImpl.pushMessage("" + browserId, routJsonObject); // 推送当前执行百分比
				
				//当前时间增加一个间隔进入下一个循环
				realTime += routeSplitTime; 
				if(realTime >= maxEndLong) {
					//推送开始预演消息
					com.alibaba.fastjson.JSONObject jsonObject3 = new com.alibaba.fastjson.JSONObject();
					jsonObject3.put("type", "end");
					jsonObject3.put("recordTime", TimeHelper.dateToLongString());
					jsonObject3.put("content", "预演结束!");
					dubboServerPushServiceImpl.pushMessage("" + browserId, jsonObject3);
					setStop();//停止
					//移除线程队列
					Iterator<RehearseThead> iterator = RehearseGlobal.rehearseThreadlist.iterator();
					while (iterator.hasNext()) {
						RehearseThead thread = iterator.next();
						if (thread.getName().contains(browserId)) {
							iterator.remove();
						}
					}
				}
			}
			try {
				RehearseThead.sleep((long) (routeSplitTime / getTimes()));
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				break;
			}
		}
	}
}
